package com.ecoolex.union.pay.retailer.api.controller;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.validation.BindingResult;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.servlet.ModelAndView;

import com.ecoolex.union.pay.retailer.core.external.pojo.nihaopay.APIRefundReqVO;
import com.ecoolex.union.pay.retailer.core.external.pojo.nihaopay.APISecurePayReqVO;
import com.ecoolex.union.pay.retailer.core.util.nihaopay.HttpRequest;
import com.ecoolex.union.pay.retailer.core.util.nihaopay.SecurityUtils;

@RestController
@RequestMapping("/order")
public class NihaoPayController {
	
	private static final Logger logger = LoggerFactory.getLogger(NihaoPayController.class);
	
	private String token = "7d22c49b9e2f030f6adc2617f485e23acfc3a10b711dc92d93d77050449dbaad";

	@PostMapping("/APISecurePay")
	@ResponseBody
	public void APISecurePay(HttpServletRequest request,
		@ModelAttribute("payReq") @Validated APISecurePayReqVO payReq, BindingResult errors,
		HttpServletResponse resp) {
		try {
			if (errors.hasErrors()) {
				resp.getWriter().print(errors.getAllErrors());
			}
			logger.info("Do API SecurePay: " + payReq.getInput());
			String result = HttpRequest.sendAuthPost(payReq.getUrl(), payReq.getInput(), "Bearer " + payReq.getToken());
			logger.info("get response from php_API: " + result);
			resp.setCharacterEncoding("UTF-8");
			resp.setHeader("Content-type", "text/html");// jquery post must return json type
			resp.getWriter().print(result);
		} catch (Exception e) {
			e.printStackTrace();
			logger.error(e.getMessage(), e);
		}
	}
	
	@RequestMapping(value = "/APIRefund", method = RequestMethod.POST)
	public @ResponseBody void APIRefund(HttpServletRequest request, @Validated APIRefundReqVO payReq,
			BindingResult errors, HttpServletResponse resp) {
		try {
			if (errors.hasErrors()) {
				resp.getWriter().print(errors.getAllErrors());
			}
			logger.info("Do API Refund: " + payReq.getInput());
			String url = payReq.getUrl().replace("{transaction_id}", payReq.getTransaction_id());
			String result = HttpRequest.sendAuthPost(url, payReq.getInput(), "Bearer " + payReq.getToken());
			logger.info("get response from php_API: " + result);
			resp.setCharacterEncoding("UTF-8");
			resp.setHeader("Content-type", "application/json");// jquery post must return json type
			resp.getWriter().print(result);
		} catch (Exception e) {
			e.printStackTrace();
			logger.error(e.getMessage(), e);
		}
	}
	
	@RequestMapping(value = "/ipn")
	public @ResponseBody void receiveIPN(HttpServletResponse response, HttpServletRequest request) {
		try {
			logger.info("ipn request:");
//			logger.info(getClientInfo(request));
//			logger.info(respVO.toString());

			BufferedReader br = new BufferedReader(new InputStreamReader(request.getInputStream()));
			String line = null;
			StringBuilder sb = new StringBuilder();
			while ((line = br.readLine()) != null) {
				sb.append(line);
			}
			logger.info("getInputStream to String: " + sb.toString());

			Map<String, String[]> params = request.getParameterMap();
			if (params.size() < 1) {
				response.setStatus(HttpServletResponse.SC_NO_CONTENT);
			}
			logger.info(request.getParameter("id"));
			StringBuilder str = new StringBuilder();
			str.append("Form Data:");
			for (String key : params.keySet()) {
				String[] values = params.get(key);
				for (int i = 0; i < values.length; i++) {
					String value = values[i];
					str.append("\r\n " + key + " -> " + value);
				}
			}
			Set<String> keySet = params.keySet();
			List<String> keyList = new ArrayList<String>(keySet);
			Collections.sort(keyList);
			StringBuffer mdStr = new StringBuffer();
			for (String key : keyList) {
				String value = params.get(key)[0];
				if (!key.equals("verify_sign") && params.get(key) != null && value != null && !value.equals("null")) {
					mdStr.append(key + "=" + value + "&");
				}
			}
			logger.info("sign prams string:" + mdStr.toString());
			mdStr.append(SecurityUtils.MD5(token).toLowerCase());
			logger.info("prams and token sign string:" + mdStr.toString());
			String verify_sign = params.get("verify_sign")[0];
			String sign = SecurityUtils.MD5(mdStr.toString()).toLowerCase();
			logger.info("sign string:" + sign);
			logger.info("verify_sign string:" + verify_sign);
			if (sign.equals(verify_sign)) {
				str.append("\r\n sign_vlidated -> true");
			} else {
				str.append("\r\n sign_vlidated -> false");
			}
			logger.info("IPN: " + str.toString());
			response.setHeader("Content-type", "application/json");// jquery post must return json type
			response.getWriter().print(str);

		} catch (Exception e) {
			e.printStackTrace();
			logger.error(e.getMessage(), e);
		}
	}

	@RequestMapping(value = "/callback")
	public ModelAndView callback(HttpServletRequest request) {
		try {
			logger.info("callback request:");
			//logger.info(getClientInfo(request));

			Map<String, String[]> params = request.getParameterMap();
			if (params.size() < 1) {
				return new ModelAndView("callback", "result", "Response status:" + HttpServletResponse.SC_NO_CONTENT);
			}
			StringBuilder str = new StringBuilder();
			str.append("Form Data:");
			for (String key : params.keySet()) {
				String[] values = params.get(key);
				for (int i = 0; i < values.length; i++) {
					String value = values[i];
					str.append("<br/>" + key + "=" + value);
				}
			}
			Set<String> keySet = params.keySet();
			List<String> keyList = new ArrayList<String>(keySet);
			Collections.sort(keyList);
			StringBuffer mdStr = new StringBuffer();
			for (String key : keyList) {
				String value = params.get(key)[0];
				if (!key.equals("verify_sign") && params.get(key) != null && value != null && !value.equals("null")) {
					mdStr.append(key + "=" + value + "&");
				}
			}
			logger.info("sign prams string:" + mdStr.toString());
			mdStr.append(SecurityUtils.MD5(token).toLowerCase());
			logger.info("prams and token sign string:" + mdStr.toString());
			String verify_sign = params.get("verify_sign")[0];
			String sign = SecurityUtils.MD5(mdStr.toString()).toLowerCase();
			logger.info("sign string:" + sign);
			logger.info("verify_sign string:" + verify_sign);
			if (sign.equals(verify_sign)) {
				str.append("<br/>sign_vlidated -> true");
			} else {
				str.append("<br/>sign_vlidated -> false");
			}
			logger.info("Callback " + str.toString());
			return new ModelAndView("callback", "result", str.toString());
		} catch (Exception e) {
			e.printStackTrace();
			logger.error(e.getMessage(), e);
			return new ModelAndView("callback", "result", e.getMessage());
		}
	}
}
